
#ifndef	__APU_INCLUDED__
#define	__APU_INCLUDED__

#define	WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <math.h>

#include "typedef.h"
#include "APU_INTERNAL.h"

//#define	QUEUE_LENGTH	4096
#define	QUEUE_LENGTH	8192



class	APU
{
public:
	APU();
	virtual	~APU();

	void	SoundSetup();
	void	SelectExSound( BYTE data );

	BOOL	SetChannelMute( INT nCH ) { m_bMute[nCH] = !m_bMute[nCH]; return m_bMute[nCH]; }

	void	QueueClear();

	void	Reset();
	BYTE	Read( WORD addr );
	void	Write( WORD addr, BYTE data );
	BYTE	ExRead( WORD addr );
	void	ExWrite( WORD addr, BYTE data );

	void	Sync();
	void	SyncDPCM( INT cycles );

	void	Process( LPBYTE lpBuffer, DWORD dwSize );


	INT	GetChannelFrequency( INT ch );
	LPSHORT	GetSoundBuffer() { return m_SoundBuffer; }

	
	void	GetFrameIRQ( INT& Cycle, BYTE& Count, BYTE& Type, BYTE& IRQ, BYTE& Occur ) {
		internal.GetFrameIRQ( Cycle, Count, Type, IRQ, Occur );
	}

	void	SetFrameIRQ( INT Cycle, BYTE Count, BYTE Type, BYTE IRQ, BYTE Occur ) {
		internal.SetFrameIRQ( Cycle, Count, Type, IRQ, Occur );
	}

	void	SaveState( LPBYTE p );
	void	LoadState( LPBYTE p );
protected:
	typedef	struct {
		INT	time;
		WORD	addr;
		BYTE	data;
		BYTE	reserved;
	} QUEUEDATA, *LPQUEUEDATA;

	typedef	struct {
		INT		rdptr;
		INT		wrptr;
		QUEUEDATA	data[QUEUE_LENGTH];
	} QUEUE, *LPQUEUE;

	void	SetQueue( INT writetime, WORD addr, BYTE data );
	BOOL	GetQueue( INT writetime, QUEUEDATA& ret );

	void	SetExQueue( INT writetime, WORD addr, BYTE data );
	BOOL	GetExQueue( INT writetime, QUEUEDATA& ret );

	void	QueueFlush();

	void	WriteProcess( WORD addr, BYTE data );
	void	WriteExProcess( WORD addr, BYTE data );



	QUEUE	queue;
	QUEUE	exqueue;

	BYTE	exsound_select;

	double	elapsed_time;

	INT	last_data, last_diff;
	INT	lowpass_filter[4];


	APU_INTERNAL 	internal;


	
	BOOL	m_bMute[16];

	SHORT	m_SoundBuffer[0x100];
private:
};


#endif	// !__APU_INCLUDED__

